#!/usr/bin/env python3
"""最简单的终端贪吃蛇（基于 curses）。

控制：方向键；按 `q` 退出。
"""

import curses
import random


def main(stdscr):
	curses.curs_set(0)
	stdscr.nodelay(True)
	stdscr.keypad(True)
	stdscr.timeout(100)

	sh, sw = stdscr.getmaxyx()

	# 初始蛇体（y, x）
	snk_x = sw // 4
	snk_y = sh // 2
	snake = [[snk_y, snk_x], [snk_y, snk_x - 1], [snk_y, snk_x - 2]]

	direction = curses.KEY_RIGHT

	def place_food():
		while True:
			f = [random.randint(1, sh - 2), random.randint(1, sw - 2)]
			if f not in snake:
				return f

	food = place_food()
	score = 0

	while True:
		stdscr.clear()

		# 边框（保护以避免小终端抛错）
		for x in range(sw):
			try:
				stdscr.addch(0, x, '#')
			except curses.error:
				pass
			try:
				stdscr.addch(sh - 1, x, '#')
			except curses.error:
				pass
		for y in range(sh):
			try:
				stdscr.addch(y, 0, '#')
			except curses.error:
				pass
			try:
				stdscr.addch(y, sw - 1, '#')
			except curses.error:
				pass

		# 画蛇
		for y, x in snake:
			try:
				stdscr.addch(y, x, 'O')
			except curses.error:
				pass

		# 画食物
		try:
			stdscr.addch(food[0], food[1], '*')
		except curses.error:
			pass

		try:
			stdscr.addstr(0, 2, f' Score: {score} ')
		except curses.error:
			pass

		key = stdscr.getch()
		if key == -1:
			key = direction
		elif key in (curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT):
			opposites = {
				curses.KEY_UP: curses.KEY_DOWN,
				curses.KEY_DOWN: curses.KEY_UP,
				curses.KEY_LEFT: curses.KEY_RIGHT,
				curses.KEY_RIGHT: curses.KEY_LEFT,
			}
			if key != opposites.get(direction):
				direction = key
		elif key in (ord('q'), ord('Q')):
			break

		head = snake[0].copy()
		if direction == curses.KEY_UP:
			head[0] -= 1
		elif direction == curses.KEY_DOWN:
			head[0] += 1
		elif direction == curses.KEY_LEFT:
			head[1] -= 1
		elif direction == curses.KEY_RIGHT:
			head[1] += 1

		# 撞墙或自撞判定
		if head[0] in (0, sh - 1) or head[1] in (0, sw - 1) or head in snake:
			msg = f' Game Over! Score: {score}. Press any key to exit '
			try:
				stdscr.addstr(sh // 2, max(0, sw // 2 - len(msg) // 2), msg)
			except curses.error:
				pass
			stdscr.nodelay(False)
			stdscr.getch()
			break

		snake.insert(0, head)
		if head == food:
			score += 1
			food = place_food()
		else:
			snake.pop()


if __name__ == '__main__':
	try:
		curses.wrapper(main)
	except KeyboardInterrupt:
		pass

